package com.agh.szepczynski.magisterka.service.controllers;

import java.util.ArrayList;
import java.util.List;

import javax.ws.rs.Consumes;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.codehaus.jackson.map.ObjectMapper;

import com.agh.szepczynski.magisterka.service.algorithms.AlgorithmRoulette;
import com.agh.szepczynski.magisterka.service.beans.dm.Person;
import com.agh.szepczynski.magisterka.service.beans.dto.CurrentEventStateResponse;
import com.agh.szepczynski.magisterka.service.beans.dto.FacebookFireAndWatchEventRequest;
import com.agh.szepczynski.magisterka.service.beans.dto.FacebookFireEventResponse;
import com.agh.szepczynski.magisterka.service.beans.fb.JsonLike;
import com.agh.szepczynski.magisterka.service.beans.fb.LikesResponse;
import com.agh.szepczynski.magisterka.service.conf.SpringContainer;
import com.agh.szepczynski.magisterka.service.events.AlgorithmState;
import com.agh.szepczynski.magisterka.service.events.Event;
import com.agh.szepczynski.magisterka.service.events.EventEngine;
import com.restfb.DefaultFacebookClient;
import com.restfb.FacebookClient;
import com.restfb.Parameter;
import com.restfb.Version;
import com.restfb.json.JsonObject;

//the url is http://localhost:8080/magisterka-service/rest/action

@Path("/facebook")
public class FacebookWatchEventController {
	
protected static final Log logger = LogFactory
		.getLog(FacebookWatchEventController.class);

	EventEngine engine = SpringContainer.getBean(EventEngine.class);

	private static final String MY_APP_ACCESS_TOKEN = "902389696451149|sa8sq8jAyB3LkScCGTC9-b7z7LU";
	FacebookClient facebookClient = new DefaultFacebookClient(MY_APP_ACCESS_TOKEN,Version.VERSION_2_3);
	// todo - this shoudlby invoked by the server, not the user but .. for debug
	// purposes
	@POST
	@Produces(MediaType.APPLICATION_JSON)
	@Consumes(MediaType.APPLICATION_JSON)
	@Path("fire_event")
	public String watch(String message) throws Exception {
		logger.info("Fire event request: " + message);
		ObjectMapper mapper = new ObjectMapper();
		FacebookFireAndWatchEventRequest request = mapper.readValue(message,
				FacebookFireAndWatchEventRequest.class);

		FacebookFireEventResponse response = fireFacebookEvent(request);

		String result = mapper.writeValueAsString(response);
		logger.info("Fire event response: " + result);
		return result;
	}

	@POST
	@Produces(MediaType.APPLICATION_JSON)
	@Consumes(MediaType.APPLICATION_JSON)
	@Path("get_current_event_state")
	public String getCurrentEventState(String message) throws Exception { 
		//logger.debug("Get current event request: " + message);
		ObjectMapper mapper = new ObjectMapper();
		FacebookFireAndWatchEventRequest request = mapper.readValue(message,
				FacebookFireAndWatchEventRequest.class);
		CurrentEventStateResponse response = createCurrentEventStateResponse(request);
		String result = mapper.writeValueAsString(response);
		//logger.debug("Current event state response: " + result);
		return result;
	}

	private CurrentEventStateResponse createCurrentEventStateResponse(
			FacebookFireAndWatchEventRequest request) {

		CurrentEventStateResponse response = new CurrentEventStateResponse();
		Event event = engine.getEvent(request.getToken());
		AlgorithmState algorithmState = event.getAlgorithmState();
		response.setAlgorithmState(algorithmState);
		response.setCreator(event.getCreator());
		response.setDateCreated(event.getDateCreated());
		response.setPeople(event.getPeople());
		response.setEventName(event.getName());
		response.setRunning(event.isAlive());
		if (event.getState() == Thread.State.TERMINATED) {
			response.setFinished(true);
		} else {
			response.setFinished(false);
		}


		response.setDateToBeFired(event.getDateToBeFired());
		// todo - change later
		
		response.setAlgorithm(event.getContestAlghoritm().getName());
		return response;
	}

	private FacebookFireEventResponse fireFacebookEvent(
			FacebookFireAndWatchEventRequest request) throws Exception {
		Event event = engine.getEvent(request.getToken());
		if (event.isAlive()) {
			throw new Exception(event.getName() + " allready running.");
		}

		List<Person> people = fetchPeople(event);
		prepareEvent(event, people);

		event.start();

		FacebookFireEventResponse response = new FacebookFireEventResponse();

		response.setDate(event.getDateCreated());
		response.setEventName(event.getName());
		response.setPeople(event.getPeople()); // todo get from fb
		response.setToken(request.getToken());
		return response;
	}

	private void prepareEvent(Event event, List<Person> people) {
		event.setPeople(people);
	}

	private List<Person> fetchPeopleMock(Event event) {
		Person person1 = new Person();
		person1.setId(7l);
		person1.setName("Tomasz");
		person1.setProfileImageUrl("https://fbcdn-profile-a.akamaihd.net/hprofile-ak-xaf1/v/t1.0-1/p320x320/11033170_857653527624764_2398327097307858857_n.jpg?oh=42696812f61276857689135bc2f44658&oe=56489C51&__gda__=1448926957_b7969e180fea2232e4a6965c11c71b9b");
		person1.setAge(18);
		Person person2 = new Person();
		person2.setId(8l);
		person2.setName("Jerzy");
		person2.setProfileImageUrl("https://fbcdn-profile-a.akamaihd.net/hprofile-ak-xaf1/v/t1.0-1/p320x320/11033170_857653527624764_2398327097307858857_n.jpg?oh=42696812f61276857689135bc2f44658&oe=56489C51&__gda__=1448926957_b7969e180fea2232e4a6965c11c71b9b");
		person2.setAge(25);
		List<Person> people = new ArrayList<Person>();
		people.add(person1);
		people.add(person2);
		return people;
	}

	private List<Person> fetchPeople(Event event) throws Exception {

		logger.info("Fetching people..");
		JsonObject json = facebookClient.fetchObject("870026676390291/likes", JsonObject.class,Parameter.with("fields","id,name,picture"),Parameter.with("limit",1000));
		logger.info(json);
		ObjectMapper objectMapper = new ObjectMapper();
		LikesResponse likesResponse = objectMapper.readValue(json.toString(),LikesResponse.class);
		logger.info(likesResponse);
		List<Person> people = new ArrayList<Person>();
		for (JsonLike like : likesResponse.data) {
				Person person = new Person();
				person.setId(like.id);
				person.setName(like.name);
				person.setProfileImageUrl(like.picture.data.url);
				people.add(person);
		}
		return people;
		
		
	}
}
